package com.hunt.system.security.shiro;

import com.hunt.dao.*;
import com.hunt.model.entity.*;
import com.hunt.util.SystemConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**com.hunt.system.security.shiro.ShiroRealm
 * @Author: ouyangan
 * @Date : 2016/10/7
 * @Description 自定义realm实现
 */
public class ShiroRealm extends AuthorizingRealm {
    
    private static final Logger log = LoggerFactory.getLogger(ShiroRealm.class);
    
    @Autowired
    private ManagementMapper managementMapper;
    
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    

    /**
     * 鉴权信息
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.debug("开始查询授权信息");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
        String userName = sysUser.getLoginName();
        String password = sysUser.getPassword();
        //通过用户名获取用户对象的所有信息
        Set<String> roles = null;
        Set<String> permissions = null;
        try {
            roles = (HashSet)redisTemplate.boundHashOps(SystemConstant.shiro_cache_prefix).get(userName+"_roles");
            permissions = (HashSet)redisTemplate.boundHashOps(SystemConstant.shiro_cache_prefix).get(userName+"_permissions");
        }catch (Exception e){
            e.printStackTrace();
        }

        if (null == roles && null ==permissions){
            SysUser user = managementMapper.selectUserCAInfoByUserId(userName,password);
            if (null == user){
                return info;
            }
            roles = new HashSet<>(50);
            permissions = new HashSet<>(50);
            if (null != user.getRoleList() && user.getRoleList().size() > 0){
                for (SysRole sysRole : user.getRoleList()) {
                    roles.add(sysRole.getName());
                    if (sysRole.getPermissionList() != null && sysRole.getPermissionList().size() > 0){
                        for (SysPermission sysPermission : sysRole.getPermissionList()) {
                            permissions.add(sysPermission.getCode());
                        }
                    }
                }
            }
            redisTemplate.boundHashOps(SystemConstant.shiro_cache_prefix).put(userName+"_roles",roles);
            redisTemplate.boundHashOps(SystemConstant.shiro_cache_prefix).put(userName+"_permissions",permissions);
        }
        info.addRoles(roles);
        info.addStringPermissions(permissions);

        log.debug("角色信息: {}", roles.toString());
        log.debug("权限信息: {}", permissions.toString());
        return info;
    }

    /**
     * 登录验证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.debug("登录验证");
        String loginName = (String) authenticationToken.getPrincipal();

            SysUser sysUser = managementMapper.selectUserByLoginName(loginName);
            if (null == sysUser){
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(loginName, sysUser.getPassword(), ByteSource.Util.bytes(sysUser.getPasswordSalt()), getName());
                return authenticationInfo;
            }
        
        AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(sysUser, sysUser.getPassword(), ByteSource.Util.bytes(sysUser.getPasswordSalt()), getName());
        return authenticationInfo;
    }
}
